﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InfoStrat.VE;
using System.Windows;
using System.Threading;
using System.Windows.Controls;

namespace BingVis.WPFClient
{
    public static class Bing3dMapBehaviors
    {
        private static bool _mapLoaded = false;
        private static VELatLong _latLong;

        /// <summary>
        /// Startup Lat Long Attached Behavior.
        /// </summary>
        
        public static VELatLong GetStartupLatLong(VEMap map)
        {
            return map.GetValue(StartupLatLongProperty) as VELatLong;
        }

        public static void SetStartupLatLong(VEMap map, VELatLong latLong)
        {
            map.SetValue(StartupLatLongProperty, latLong);
        }

        public static readonly DependencyProperty StartupLatLongProperty =
            DependencyProperty.RegisterAttached("StartupLatLong", typeof(VELatLong), typeof(Bing3dMapBehaviors), new UIPropertyMetadata(new VELatLong(), OnStartupLatLongChanged));

        private static void OnStartupLatLongChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            // TODO: Some validation on depObj and e.NewValue
            var map = depObj as VEMap;
            _latLong = e.NewValue as VELatLong;
            
            // An offset because we have a tilt to the camera.
            _latLong.Latitude = _latLong.Latitude - .0020;

            var initialAlt = _latLong.Altitude;

            // Once the map is loaded, wait one second then fly to to specified location.            
            map.MapLoaded += (x, y) => { Thread.Sleep(1000); map.FlyTo(_latLong, -80, map.Yaw, initialAlt); _mapLoaded = true; };
        }

        /// <summary>
        /// Fly To Lat Long Attached Behavior.
        /// </summary>
        
        public static VELatLong GetFlyLatLong(VEMap map)
        {
            return (VELatLong)map.GetValue(FlyLatLongProperty);
        }

        public static void SetFlyLatLong(VEMap map, VELatLong alt)
        {
            map.SetValue(FlyLatLongProperty, alt);
        }
                
        public static readonly DependencyProperty FlyLatLongProperty =
            DependencyProperty.RegisterAttached("FlyLatLong", typeof(VELatLong), typeof(Bing3dMapBehaviors), new UIPropertyMetadata(new VELatLong(), OnFlyLatLongChanged));

        private static void OnFlyLatLongChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            if (!_mapLoaded)
                return;

            var map = depObj as VEMap;
            var jumpTo = e.NewValue as VELatLong;

            jumpTo = new VELatLong(jumpTo.Latitude - .0025, jumpTo.Longitude, jumpTo.Altitude);

            map.FlyTo(jumpTo, -75, 0, jumpTo.Altitude);
        }

        /// <summary>
        /// Jump Lat Long Attached Behavior.
        /// </summary>
        
        public static VELatLong GetJumpLatLong(VEMap map)
        {
            return (VELatLong)map.GetValue(JumpLatLongProperty);
        }

        public static void SetJumpLatLong(VEMap map, VELatLong alt)
        {
            map.SetValue(JumpLatLongProperty, alt);
        }

        public static readonly DependencyProperty JumpLatLongProperty =
            DependencyProperty.RegisterAttached("JumpLatLong", typeof(VELatLong), typeof(Bing3dMapBehaviors), new UIPropertyMetadata(new VELatLong(), OnJumpLatLongChanged));

        private static void OnJumpLatLongChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            if (!_mapLoaded)
                return;

            var map = depObj as VEMap;
            var jumpTo = e.NewValue as VELatLong;

            jumpTo = new VELatLong(jumpTo.Latitude - .0025, jumpTo.Longitude, jumpTo.Altitude);
            
            map.JumpTo(jumpTo, 0, -75, 0, jumpTo.Altitude);
        }

        /// 
        /// The Show3DBuildings attached Property.
        /// 

        public static bool GetShow3DBuildings(VEMap map)
        {
            return (bool)map.GetValue(Show3DBuildingsProperty);
        }

        public static void SetShow3DBuildings(VEMap map, bool showEm)
        {
            map.SetValue(Show3DBuildingsProperty, showEm);
        }

        public static readonly DependencyProperty Show3DBuildingsProperty =
            DependencyProperty.RegisterAttached("Show3DBuildings", typeof(bool), typeof(Bing3dMapBehaviors), new UIPropertyMetadata(true, OnShow3DBuildingsChanged));

        private static void OnShow3DBuildingsChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {   
            var map = depObj as VEMap;
            var showBuildings = (bool)e.NewValue;

            if (!_mapLoaded)
                map.MapLoaded += new EventHandler((x, y) => ((VEMap)x).ShowBuildings = showBuildings);
            else
                map.ShowBuildings = showBuildings;
        }


    }
}
